@@ -11,7 +11,7 @@ module Agents |
||
11 | 11 |
description <<-MD |
12 | 12 |
The Shell Command Agent will execute commands on your local system, returning the output. |
13 | 13 |
|
14 |
- `command` specifies the command (either a shell command line string or an array of command line arguments) to be executed, and `path` will tell ShellCommandAgent in what directory to run this command. |
|
14 |
+ `command` specifies the command (either a shell command line string or an array of command line arguments) to be executed, and `path` will tell ShellCommandAgent in what directory to run this command. The content of `stdin` will be fed to the command via the standard input. |
|
15 | 15 |
|
16 | 16 |
`expected_update_period_in_days` is used to determine if the Agent is working. |
17 | 17 |
|
@@ -50,6 +50,12 @@ module Agents |
||
50 | 50 |
errors.add(:base, "The path, command, and expected_update_period_in_days fields are all required.") |
51 | 51 |
end |
52 | 52 |
|
53 |
+ case options['stdin'] |
|
54 |
+ when String, nil |
|
55 |
+ else |
|
56 |
+ errors.add(:base, "stdin must be a string.") |
|
57 |
+ end |
|
58 |
+ |
|
53 | 59 |
unless Array(options['command']).all? { |o| o.is_a?(String) } |
54 | 60 |
errors.add(:base, "command must be a shell command line string or an array of command line arguments.") |
55 | 61 |
end |
@@ -79,8 +85,9 @@ module Agents |
||
79 | 85 |
if Agents::ShellCommandAgent.should_run? |
80 | 86 |
command = opts['command'] |
81 | 87 |
path = opts['path'] |
88 |
+ stdin = opts['stdin'] |
|
82 | 89 |
|
83 |
- result, errors, exit_status = run_command(path, command) |
|
90 |
+ result, errors, exit_status = run_command(path, command, stdin) |
|
84 | 91 |
|
85 | 92 |
vals = {"command" => command, "path" => path, "exit_status" => exit_status, "errors" => errors, "output" => result} |
86 | 93 |
created_event = create_event :payload => vals |
@@ -91,15 +98,22 @@ module Agents |
||
91 | 98 |
end |
92 | 99 |
end |
93 | 100 |
|
94 |
- def run_command(path, command) |
|
101 |
+ def run_command(path, command, stdin) |
|
95 | 102 |
begin |
96 | 103 |
rout, wout = IO.pipe |
97 | 104 |
rerr, werr = IO.pipe |
105 |
+ rin, win = IO.pipe |
|
98 | 106 |
|
99 |
- pid = spawn(*command, chdir: path, out: wout, err: werr) |
|
107 |
+ pid = spawn(*command, chdir: path, out: wout, err: werr, in: rin) |
|
100 | 108 |
|
101 | 109 |
wout.close |
102 | 110 |
werr.close |
111 |
+ rin.close |
|
112 |
+ |
|
113 |
+ if stdin |
|
114 |
+ win.write stdin |
|
115 |
+ win.close |
|
116 |
+ end |
|
103 | 117 |
|
104 | 118 |
(result = rout.read).strip! |
105 | 119 |
(errors = rerr.read).strip! |
@@ -12,7 +12,8 @@ describe Agents::ShellCommandAgent do |
||
12 | 12 |
|
13 | 13 |
@valid_params2 = { |
14 | 14 |
path: @valid_path, |
15 |
- command: [RbConfig.ruby, '-e', 'puts "hello, world."; STDERR.puts "warning!"'], |
|
15 |
+ command: [RbConfig.ruby, '-e', 'puts "hello, #{STDIN.eof? ? "world" : STDIN.read.strip}."; STDERR.puts "warning!"'], |
|
16 |
+ stdin: "{{name}}", |
|
16 | 17 |
expected_update_period_in_days: '1', |
17 | 18 |
} |
18 | 19 |
|
@@ -27,7 +28,8 @@ describe Agents::ShellCommandAgent do |
||
27 | 28 |
@event = Event.new |
28 | 29 |
@event.agent = agents(:jane_weather_agent) |
29 | 30 |
@event.payload = { |
30 |
- :cmd => "ls" |
|
31 |
+ 'name' => 'Huginn', |
|
32 |
+ 'cmd' => 'ls', |
|
31 | 33 |
} |
32 | 34 |
@event.save! |
33 | 35 |
|
@@ -58,7 +60,7 @@ describe Agents::ShellCommandAgent do |
||
58 | 60 |
|
59 | 61 |
describe "#working?" do |
60 | 62 |
it "generating events as scheduled" do |
61 |
- stub(@checker).run_command(@valid_path, 'pwd') { ["fake pwd output", "", 0] } |
|
63 |
+ stub(@checker).run_command(@valid_path, 'pwd', nil) { ["fake pwd output", "", 0] } |
|
62 | 64 |
|
63 | 65 |
expect(@checker).not_to be_working |
64 | 66 |
@checker.check |
@@ -71,7 +73,7 @@ describe Agents::ShellCommandAgent do |
||
71 | 73 |
|
72 | 74 |
describe "#check" do |
73 | 75 |
before do |
74 |
- stub(@checker).run_command(@valid_path, 'pwd') { ["fake pwd output", "", 0] } |
|
76 |
+ stub(@checker).run_command(@valid_path, 'pwd', nil) { ["fake pwd output", "", 0] } |
|
75 | 77 |
end |
76 | 78 |
|
77 | 79 |
it "should create an event when checking" do |
@@ -84,7 +86,7 @@ describe Agents::ShellCommandAgent do |
||
84 | 86 |
it "should create an event when checking (unstubbed)" do |
85 | 87 |
expect { @checker2.check }.to change { Event.count }.by(1) |
86 | 88 |
expect(Event.last.payload[:path]).to eq(@valid_path) |
87 |
- expect(Event.last.payload[:command]).to eq([RbConfig.ruby, '-e', 'puts "hello, world."; STDERR.puts "warning!"']) |
|
89 |
+ expect(Event.last.payload[:command]).to eq([RbConfig.ruby, '-e', 'puts "hello, #{STDIN.eof? ? "world" : STDIN.read.strip}."; STDERR.puts "warning!"']) |
|
88 | 90 |
expect(Event.last.payload[:output]).to eq('hello, world.') |
89 | 91 |
expect(Event.last.payload[:errors]).to eq('warning!') |
90 | 92 |
end |
@@ -97,7 +99,7 @@ describe Agents::ShellCommandAgent do |
||
97 | 99 |
|
98 | 100 |
describe "#receive" do |
99 | 101 |
before do |
100 |
- stub(@checker).run_command(@valid_path, @event.payload[:cmd]) { ["fake ls output", "", 0] } |
|
102 |
+ stub(@checker).run_command(@valid_path, @event.payload[:cmd], nil) { ["fake ls output", "", 0] } |
|
101 | 103 |
end |
102 | 104 |
|
103 | 105 |
it "creates events" do |
@@ -108,6 +110,13 @@ describe Agents::ShellCommandAgent do |
||
108 | 110 |
expect(Event.last.payload[:output]).to eq("fake ls output") |
109 | 111 |
end |
110 | 112 |
|
113 |
+ it "creates events (unstubbed)" do |
|
114 |
+ @checker2.receive([@event]) |
|
115 |
+ expect(Event.last.payload[:path]).to eq(@valid_path) |
|
116 |
+ expect(Event.last.payload[:output]).to eq('hello, Huginn.') |
|
117 |
+ expect(Event.last.payload[:errors]).to eq('warning!') |
|
118 |
+ end |
|
119 |
+ |
|
111 | 120 |
it "does not run when should_run? is false" do |
112 | 121 |
stub(Agents::ShellCommandAgent).should_run? { false } |
113 | 122 |
|